home *** CD-ROM | disk | FTP | other *** search
- title "TNC1 BOOT MODULE"
- nam tncbug
-
- **
- * Copyright 1987 by Marc Kaufman, WB6ECE
- * All Rights Reserved.
- *
- * Permission is given for non-commercial use and distribution,
- * provided that this notice is retained.
- **
-
- * Boot and debug ROM module for the TAPR TNC1
- * Written by Marc Kaufman, WB6ECE
- *
- * Correction history:
- *
- * 3/87 WB6ECE - Initial Release
-
- * NOTE -
- * It may seem to be overkill to have a debug program that is
- * (possibly) bigger than the program it loads. But a few well
- * chosen features make it easier to bring software up.
-
- * Based on Motorola's 'mikbug' programs, but entirely rewritten
- * Commands (see documentation for full description)
- *
- * G Go to target program
- * M or @ Memory examine/change
- * P Poke memory without readback
- * S Display contents of target stack
- * CC A B DP X Y U PC S
- * R or # Register examine/change
- * D Dump 8 bytes of memory
- * W Watch memory location for changes
- * L Load a Program into RAM (S-record format)
-
- * Hardware addresses
-
- acia equ $2010 6551 UART
- acchar equ acia
- acstat equ acia+1
- accmnd equ acia+2
- acctrl equ acia+3
-
- pia equ $2020 6520 parallel output
- pra equ pia register A
- pcra equ pia+1 control A
- prb equ pia+2 register B
- pcrb equ pia+3 control B
-
- via equ $2040 6522 timer chip
- vorb equ via output register B
- vora equ via+15 output register A, no handshake
- vddrb equ via+2 data direction register B
- vddra equ via+3 data direction register A
- vacr equ via+11 auxiliary control register
- vpcr equ via+12 peripheral control register
- vifr equ via+13 interrupt flag register
- vier equ via+14 interrupt enable register
-
- * NOTE: this chip inverts Address and Data leads!! (both)
- hdlc equ $2800 WD 1933 HDLC chip
- hcr1 equ hdlc+7 control register 1
- hcr2 equ hdlc+6 control register 2
- hcr3 equ hdlc+5 control register 3
- hrhr equ hdlc+4 receive holding register
- hthr equ hdlc+3 transmit holding register
- hir equ hdlc+3 interrupt register
- hsr equ hdlc+2 status register
-
- ram equ $0000 bank 0 ram ($0000 - $1fff)
- ram1 equ $4000 bank 1 ram ($4000 - $5fff)
- rom equ $e000 top rom ($e000 - $ffff)
-
- CR equ $0d carriage return
- LF equ $0a line feed
-
- *
- dsect
- org ram data starts in low ram
-
- * interrupt re-vector area: parallel to fff0-ffff
-
- igo rmb 2 0000 - program start point
- iswi3 rmb 2 0002
- iswi2 rmb 2 0004
- ifirq rmb 2 0006
- iirq rmb 2 0008
- iswi rmb 2 000a
- inmi rmb 2 000c - last vector used
- ireset rmb 2 full reset
-
- cksum rmb 1 loader checksum
- bytect rmb 1 loader byte count
- addr rmb 2 loader address field
- echofl rmb 1 flag to enable character echo (0 = off)
- svchr rmb 1
- svchra rmb 1
- svchrx rmb 2
- oldval rmb 4 for watching
- newval rmb 4
- saves rmb 2 saved stack pointer
-
- rmb 12 initial stack, big enough for irq push
- myistack equ *
-
- rmb 50
- mystack equ * stack space for debugger
-
- csect
-
- * interrupt vector list
- org $fff2 interrupt vectors
-
- fdb jswi3
- fdb jswi2
- fdb jfirq
- fdb jirq
- fdb jswi
- fdb jnmi
- fdb bugstart
-
- * main code space
- org $f800 top 2K, so it fits into 2716
-
- * just to get it over with, interrupt re-vectoring goes here
-
- jswi3 jmp [iswi3]
- jswi2 jmp [iswi2]
- jfirq jmp [ifirq]
- jirq jmp [iirq]
- jswi jmp [iswi]
- jnmi jmp [inmi]
-
- * Main startup of debug monitor - on reset
-
- bugstart
- orcc #$50 turn off interrupts (FIRQ + IRQ)
- clra
- sta <echofl turn off uart echo
- tfr a,dp clear base page register
-
- * reset 6520
- sta pcra disable pia-A
- sta pcrb disable pia-B
-
- * reset 6522
- sta vpcr clear CA2 to reset HDLC chip
- sta vacr reset 6522 timer and shift register
- ldd #$fff0
- sta vora set A output bits to '1'
- stb vddra turning off NOVROM access
- ldd #$ff3f
- sta vorb set B output bits to '1'
- stb vddrb driving NOVROM address to all 1's
- lda #$ce
- sta vpcr reset 6522 control modes (CA2 = 1)
- lda #$7f
- sta vier disable all 6522 interrupts
- sta vifr clear all 6522 interrupts
-
- lds #0
- ldx #bugcont default return for interrupts
- lda #8 number of things to fill
- .initi stx 0,s++
- decb
- bne .initi
- ldx #bugstart full reset
- stx <ireset
- lds #myistack private stack
-
- lda #14 9600 baud select for acia
- bsr areset start at 9600 (hunt mode)
- .initb jsr arcv read a character
- cmpb #CR look for CR at 9600
- beq bugcont OK as is (stay at 9600)
- ldb #12
- cmpa #$e6
- beq .bset 4800 baud
- ldb #10
- cmpa #$78
- beq .bset 2400 baud
- ldb #8
- cmpa #$80
- beq .bset 1200 baud
- ldb #6
- tsta (300 baud)
- bne .initb none of the above, continue waiting
-
- .bset orb #$10 8 bit word, 1 stop, internal clock
- stb acctrl
- swi get to bugcont via interrupt
-
- * reentry point, does not reset acia speed or vectors
-
- bugcont orcc #$50 turn off interrupts (FIRQ + IRQ)
- clra
- tfr a,dp clear base page register
- sts <saves save user stack pointer
-
- contrl lds #mystack
- bsr acrlf send prompt (cr-lf->)
- lda #'>'
- bsr asend
- lda acchar trash any character in the receiver
- clr <echofl turn off echo
-
- cnget jsr arcv get command character
- stb <svchr save it (upper case)
- ldy #ctable
- cloop lda 0,y+
- beq cnget not found, ignore
- ldx 0,y++
- cmpa <svchr
- bne cloop
- bsr asend echo command
- bsr outs add space
- sta <echofl turn on echo
- jmp 0,x execute command
-
- ctable fcb 'G' command action table
- fdb go
- fcb 'M'
- fdb change
- fcb '@'
- fdb change
- fcb 'P'
- fdb poke
- fcb 'S'
- fdb sregs
- fcb 'R'
- fdb rregs
- fcb '#'
- fdb rregs
- fcb 'D'
- fdb dump
- fcb 'W'
- fdb watch
- fcb 'L'
- fdb load
- fcb CR
- fdb contrl
- fcb 0 end of table
- * ACIA routines
-
- * ARESET - reset acia (interrupts off)
- * enter - Speed code in A
- *
- areset sta acstat Programmed reset
- anda #$0f isolate speed code
- ora #$10 8 bit word, 1 stop, internal clock
- sta acctrl
- lda #$0b no parity, enable xmt, rcv, no interrupt
- sta accmnd
- rts
-
- * ASEND - send one character to acia (busy wait)
- * enter - character in A
- *
- asend ldb acstat
- bitb #$10
- beq asend wait for previous character to clear
- sta acchar send this one
- rts
-
- * ACRLF - print cr,lf
- *
- acrlf lda #CR cr
- bsr asend
- lda #LF lf
- bra asend
-
- * PRINT - print a string
- * entry - address of string in X
- *
- print lda 0,x+ get next character
- beq .prix done
- bsr asend
- bra print
- .prix rts
-
- * OUT2H - put out hex digit (2 output bytes)
- * entry - address of byte in X
- *
- out2h lda 0,x+
- sta <svchr
- bsr outhl output left digit
- lda <svchr
- bra outrl output right digit
-
- *
- outhl lsra output left hex digit
- lsra
- lsra
- lsra
- outrl anda #$f output right hex digit
- adda #'0'
- cmpa #'9'
- bls asend 0-9
- adda #'A'-'9'-1
- bra asend A-F
-
- *
- out4hs bsr out2h output 2 bytes plus space
- out2hs bsr out2h output 1 byte plus space
- outs lda #' '
- bra asend
-
- out8hs bsr o4h output 4 bytes separated by spaces
- o4h bsr out2hs
- bra out2hs
-
- echoa bsr acrlf echo address
- ldx #addr
- bsr out4hs print it
- ldx <addr restore address to X
- rts
-
- * ARCV - wait for and read one character from acia
- * exit - character in A (8 bits)
- * character in B (masked to 7 bits and upper case)
- *
- arcv ldb acstat
- bitb #$08
- beq arcv wait for character to arrive
- lda acchar
- tab
- andb #$7f
- cmpb #'a'
- blt .arcve not alphabetic
- cmpb #'z'
- bgt .arcve
- subb #'a'-'A' convert to upper case
- .arcve tst <echofl echo this character?
- beq .arcvx no
- std <svchrx yes, save character
- tba
- bsr asend echo upper case variant
- ldd <svchrx
- .arcvx rts
-
- * INHEX - read a single hex digit into B
- *
- inhex bsr arcv get a character
- inhexa subb #'0' enter here if character in B already
- lbmi contrl error
- cmpb #9
- ble .in1hg in decimal range, OK
- cmpb #'A'-'0'
- lbmi contrl not A-F
- cmpb #'F'-'0'
- lbgt contrl
- subb #'A'-'9'-1
- .in1hg rts
-
- * BYTE - read a hex byte (two frames)
- * exit with character in A, cksum updated
- *
- byte bsr inhex get hex character
- byteb aslb
- aslb
- aslb
- aslb
- stb <svchr save it
- bsr inhex
- addb <svchr
- tba
- addb <cksum
- stb <cksum
- rts
-
- bytea bsr inhexa have character already, enter late
- bra byteb
-
- * GETA - read a hex address
- * exit with address in 'addr' and X
- *
- geta bsr byte read 2 frames
- sta <addr
- bsr byte
- sta <addr+1
- ldx <addr
- rts
-
- * G - go to program... via rti
- *
- go lds <saves location of return stack
- rti
-
- * M - change memory (M AAAA DD NN)
- *
- change bsr geta get starting address
- bsr outs
- bra .cha52
-
- .cha51 bsr echoa echo address to examine
- .cha52 jsr out2hs print (old) data
- stx <addr save next address
- bsr arcv input one character
- cmpb #CR
- beq .cha51 CR, go to next address
- bsr bytea input new data
- sta 0,-x change memory
- cmpa 0,x
- beq .cha51 did store correctly
-
- lda #'?'
- jsr asend error in store, print value seen
- jsr out2hs
- bra .cha51 continue anyway
-
- * P - poke memory (P AAAA NN)
- *
- poke bsr geta get starting address
- jsr outs
- bra .pok5a
-
- .pok51 jsr echoa echo address to poke
- .pok5a jsr arcv input one character
- cmpb #CR
- beq .pok52 skip this address
- bsr bytea input data to poke
- sta 0,x store it
- .pok52 inx
- stx <addr next address
- bra .pok51 continue
-
- * S - print registers from stack (CC A B DP X Y U PC S)
- *
- sregs ldx #srhead
- jsr print
- ldx <saves saved stack pointer
- jsr out2hs condition codes
- jsr out2hs A
- jsr out2hs B
- jsr out2hs DP
- jsr out4hs X
- jsr out4hs Y
- jsr out4hs U
- jsr out4hs PC
- ldx #saves
- jsr out4hs S
- jmp contrl
-
- srhead fcc ' CC A B DP X Y U PC S'
- fcb CR,LF
- fcc,n ' '
-
- * R - (R r DD NN) examine and change individual stack registers
- *
- rregs jsr arcv get register name
- stb <svchra
- ldy #rtable look up register name and offset
- rloop lda 0,y+ get register name
- lbeq contrl not found
- ldx 0,y++ offset and length
- cmpa <svchra
- bne rloop not this one, keep looking
- jsr outs add space after register name
-
- tfr x,d move offset to A, length to D
- ldx <saves user stack pointer
- leax a,x address of register value
- tsta special cases
- bpl rlmod
- ldx #saves stack pointer case
-
- rlmod stx <addr save address of field
- stb <svchra save length of field
- bne rlp4 print long field
- jsr out2hs
- bra rlp
- rlp4 jsr out4hs
- rlp ldx <addr saved address of field
- jsr byte first byte of field
- sta 0,x+
- tst <svchra is this a long field
- lbne contrl no
- jsr byte modify second byte of field
- sta 0,x
- jmp contrl
-
- rtable fcb 'C',0,0 condition codes
- fcb 'A',1,0 A
- fcb 'B',2,0 B
- fcb 'D',1,2 D
- fcb 'G',3,0 DP
- fcb 'X',4,2 X
- fcb 'Y',6,2 Y
- fcb 'U',8,2 U
- fcb 'P',10,2 PC
- fcb 'S',-1,2 S
- fcb 0 end of table
-
- * D - dump 8 bytes of memory (D AAAA) (D) TO CONTINUE
- *
- dump jsr geta get starting address
- jsr outs
- bra .dump1
-
- .dlp jsr echoa
- .dump1 jsr out8hs
- stx <addr next address
- jsr arcv
- cmpb #'D' do we continue
- beq .dlp yes
- jmp contrl no
-
- * W - watch memory (W AAAA)
- * it re-displays on changes.
- * type hex to make changes:
- * space + hex changes, "-" does not.
- *
- * type CR to exit
- *
- watch jsr geta watch address
- .w0 ldx <addr
- lda 0,x
- coma
- sta <oldval force print first time
-
- .w1 ldx <addr
- ldd 0,x get latest values
- std <newval
- ldd 2,x
- std <newval+2
-
- ldd <newval
- cmpd <oldval
- bne .wd different
- ldd <newval+2
- cmpd <oldval+2
- beq .wa
-
- .wd jsr acrlf print new value
- ldx #newval
- jsr out8hs
- ldd <newval now turn print off
- std <oldval
- ldd <newval+2
- std <oldval+2
-
- .wa ldb acstat check for character pending
- bitb #$08
- beq .w1 no
- jsr arcv get character
- ldx <addr re-establish X register
- cmpa #CR CR
- lbeq contrl exit now
- bra .wc1
-
- .wc inx
- jsr arcv
- cmpa #CR CR
- beq .w0 end of mods
- .wc1 cmpa #'-' skip this byte?
- beq .wc yes
- cmpa #' '
- lbne contrl exit
- jsr byte get a new byte
- sta 0,x
- bra .wc
-
- * L - load S-records
- *
- load equ *
- clr <echofl turn off echo of load
- .load1 jsr arcv
- cmpb #'S'
- bne .load1 wait for record start
- jsr arcv get record type
- pshs a save it
- clr <cksum
- jsr byte read a hex byte
- suba #2
- sta <bytect save record byte count
- jsr geta get load address
- puls a recover record type
- cmpa #'9'
- beq .load5 eof record, end of load
- cmpa #'1'
- bne .load1 not binary record, skip it
-
- .load2 jsr byte read a byte
- dec <bytect
- beq .load3 if through with data
- sta 0,x+
- bra .load2
-
- .load3 inc <cksum check checksum
- beq .load1 cksum ok, get next line
- .load4 lda #'?' error response
- jsr asend
- jmp contrl
-
- .load5 jsr byte check checksum
- dec <bytect
- bne .load4 error, should be 3 bytes only
- inc <cksum
- bne .load4 error, checksum fails
- cmpx #0
- beq .load6 no start address given, dont store
- stx <igo start address from eof record
- .load6 ldx <igo starting address
- ldy <saves
- stx 10,y dump start address into PC field
- jmp contrl done
-
- end bugstart
-